if select(2, UnitClass('player')) ~= "SHAMAN" then
	return
end
local _G = getfenv(0);
local AceOO = AceLibrary("AceOO-2.0");
local BS = AceLibrary("Babble-Spell-2.2");
local L = AceLibrary("AceLocale-2.2"):new("Yata");
if (not Yata.Class) then Yata.Class = {} end;
Yata.Class.TotemBar = AceOO.Class("AceEvent-2.0");
Yata.Class.TotemBar.virtual = true;
Yata.Class.ITotemBar = AceOO.Interface{CreateBar = "function", Reset = "function", TotemButtons = "function"};
Yata.Class.FlexTotemBar = AceOO.Class(Yata.Class.TotemBar, Yata.Class.ITotemBar);

-------------
-- Styles --
-------------

-- Method originally found in Bartender 3 by nevcairiel
local function ShortenKeyBinding(text)
	text = string.gsub(text, "CTRL--", "|c00FF9966C|r")
	text = string.gsub(text, "STRG--", "|c00CCCC00S|r")
	text = string.gsub(text, "ALT--", "|c009966CCA|r")
	text = string.gsub(text, "SHIFT--", "|c00CCCC00S|r")
	text = string.gsub(text, "Num Pad ", "NP")
	text = string.gsub(text, "Mouse Button ", "M")
	text = string.gsub(text, "Middle Mouse", "MM")
	text = string.gsub(text, "Backspace", "Bs")
	text = string.gsub(text, "Spacebar", "Sp")
	text = string.gsub(text, "Delete", "De")
	text = string.gsub(text, "Home", "Ho")
	text = string.gsub(text, "End", "En")
	text = string.gsub(text, "Arrow", "")
	text = string.gsub(text, "Insert", "Ins")
	text = string.gsub(text, "Page Up", "Pu")
	text = string.gsub(text, "Page Down", "Pd")
	text = string.gsub(text, "Down ", "D")
	text = string.gsub(text, "Up ", "U")
	text = string.gsub(text, "Left ", "L")
	text = string.gsub(text, "Right ", "R")
	
	return text
end


Yata.Styles = {
		["Default"] = {Name = L["Default"], Spacing = 0, HGap = -1},
		["HGap"] = {Name = L["HorizontalGap"], Spacing = 0, HGap = 0,},
		["Zoomed"] = { Name = L["Zoomed"], Coords = {0.07,0.93,0.07,0.93}, Spacing = 0},
		["Dreamlayout"] = { Name = L["Dreamlayout"], Padding = 3, Coords = {0.07,0.93,0.07,0.93}, Spacing = 0, CustomFrame = true, 
			FrameFunc = function(button) 
			button.CustomFrame = CreateFrame("Frame", button.Frame:GetName().."DL",button.Frame);
			button.CustomFrame:ClearAllPoints();
			button.CustomFrame:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 1, edgeFile = "", edgeSize = 0, insets = {left = 0, right = 0, top = 0, bottom = 0},});
			button.CustomFrame:SetBackdropColor(0, 0, 0, 0.6);
			button.CustomFrame:SetAllPoints(button.Frame);
			button.CustomFrame:SetFrameLevel(0);
		end,
		},
}

function Yata.Class.TotemBar.prototype:SetStyle(stylename)
	local style = Yata.Styles[stylename];
	local spacing = 5;
	local hgap = 0;
	if(style) then
		for k,b in self:TotemButtons() do 
			-- first reset most of it --
			if(b.CustomFrame) then 
				b.CustomFrame:Hide();
				b.CustomFrame = nil;
			end
			b.Icon:SetTexCoord(0,1,0,1);
			b.Icon:SetAllPoints(b.Frame);
			-- now do style
			if(style.Coords) then
				b.Icon:SetTexCoord(style.Coords[1],style.Coords[2],style.Coords[3],style.Coords[4]);	
			end
			if(style.CustomFrame) then
				style.FrameFunc(b);			
				b.CustomFrame:Show();
			end
			if(style.Padding) then
				b.Icon:SetPoint("TOPLEFT", b.Frame, "TOPLEFT", style.Padding, -style.Padding);
				b.Icon:SetPoint("BOTTOMRIGHT",b.Frame, "BOTTOMRIGHT",  -style.Padding, style.Padding);
			end
		end
		spacing = style.Spacing;
		if(style.HGap) then
			hgap = style.HGap
		end
	end
	self.db.profile.ButtonStyle = stylename;
	local buttonid = 0;
	for k,b in self:TotemButtons() do
		b.Frame:ClearAllPoints();
		buttonid = b.ButtonID;
		if(buttonid == 1) then
		    b.Frame:SetPoint("BOTTOMLEFT", self.Header.Frame,"BOTTOMLEFT", 20, 0);
		elseif(buttonid < 5) then
		    if(self.db.profile.VerticalBar) then
		    	b.Frame:SetPoint("TOPLEFT", anchorTo.Frame, "BOTTOMLEFT", 0, spacing+hgap);
		    else
		    	b.Frame:SetPoint("BOTTOMLEFT", anchorTo.Frame, "BOTTOMRIGHT", spacing+hgap,0);
		    end
		else
		    if(math.fmod(buttonid,10) == 1) then
		    	anchorTo = self.Buttons[math.floor(buttonid/10)];
		    else 
		    	anchorTo = self.Buttons[buttonid-1];
		    end
		    if(anchorTo) then
			    	if(self.db.profile.InvertBar and not self.db.profile.VerticalBar) then
			    		b.Frame:SetPoint( "TOP", anchorTo.Frame, "BOTTOM", 0, -spacing);
			    	elseif(self.db.profile.InvertBar and self.db.profile.VerticalBar) then
			    		b.Frame:SetPoint( "LEFT", anchorTo.Frame, "RIGHT", -spacing, 0);
			    	elseif(not self.db.profile.InvertBar and not self.db.profile.VerticalBar) then
			    		b.Frame:SetPoint( "BOTTOM", anchorTo.Frame, "TOP", 0, spacing);
			    	elseif(not self.db.profile.InvertBar and self.db.profile.VerticalBar) then
			    		b.Frame:SetPoint( "RIGHT", anchorTo.Frame, "LEFT", spacing, 0);
			    	end
		    end
		    b.Frame:SetScale(self.db.profile.PopupButtonScale);
		end
		anchorTo = b;
	end
end

------------------------
-- Bar template stuff --
------------------------
function Yata.Class.TotemBar.prototype:LoadConfig()
	local x = 0;
	local y = 0;
	local scale = 1;
	if(self.db.profile.Position) then
		x = self.db.profile.Position.x;
		y = self.db.profile.Position.y;
		scale = self.Header.Frame:GetEffectiveScale();
	else
		self.Header.Frame:ClearAllPoints();
		self.Header.Frame:SetPoint( "CENTER", WorldFrame, "CENTER", 0,0 );
		scale = self.Header.Frame:GetEffectiveScale();
		x = self.Header.Frame:GetLeft()*scale;
		y = self.Header.Frame:GetBottom()*scale;
	end
	local anchorTo;
	self.Header.Frame:ClearAllPoints();
	self.Header.Frame:SetPoint("BOTTOMLEFT", UIParent,"BOTTOMLEFT", x/scale, y/scale);
	self.Header.Frame:SetScale(self.db.profile.ButtonScale);
	self:SetStyle(self.db.profile.ButtonStyle);
	self:HeaderMovement();
	self:SaveConfig();
	Yata:EditMacro();
	self:CreateHideShowButtons();
end

function Yata.Class.TotemBar.prototype:SaveConfig()
	if not self.db.profile.Position then 
		self.db.profile.Position = {};
	end
	local scale = self.Header.Frame:GetEffectiveScale();
	scale = scale / self.db.profile.ButtonScale;
	local x = self.Header.Frame:GetLeft()*scale;
	local y = self.Header.Frame:GetBottom()*scale; 
	self.db.profile.Position.x = x;
	self.db.profile.Position.y = y;
end

function Yata.Class.TotemBar.prototype:Reset()
	if(not InCombatLockdown()) then
		self.db.profile.Position = nil;
		self:LoadConfig();
	end
end


function Yata.Class.TotemBar.prototype:Hide()
	self.Header.Frame:Hide();
end

function Yata.Class.TotemBar.prototype:Show()
	self.Header.Frame:Show();
end

function Yata.Class.TotemBar.prototype:TotemButtons()
	return next, self.Buttons, nil;
end

function Yata.Class.TotemBar.prototype:init(db)
	Yata.Class.TotemBar.super.prototype.init(self);
	self.db = db;
	self:RegisterEvent("SPELL_UPDATE_COOLDOWN", "BarUpdateHandler");
	local totem = Yata.TotemData[BS["Stoneskin Totem"]];
	if(totem) then 
		self.CooldownID = totem[#totem].SpellID;
	end
end

-----------------
-- Keybindings --
-----------------

function Yata.Class.TotemBar.prototype:SetupKeybindings()
	local buttonid = 0;
	for k,b in self:TotemButtons() do
		buttonid = b.ButtonID;
		self:CreateTotemKeybindingOption(buttonid);
		local hotkey = _G[b.Frame:GetName() .. "HotKey"];
		hotkey:SetText( ShortenKeyBinding(GetBindingText(self.db.profile.Keybindings[buttonid], "KEY_")));
	end
end

-- Binding functions basicly from ClosetGnome by rabbit
function Yata.Class.TotemBar.prototype:ClearBinding(ID)
	if (not ID) then return end
	local oldbind = self.db.profile.Keybindings[ID];
	if not oldbind then return end
	self.db.profile.Keybindings[ID] = nil;
	SetBinding(oldbind);
	local hotkey = _G[self.Buttons[ID].Frame:GetName() .. "HotKey"];
	hotkey:SetText("");
end

function Yata.Class.TotemBar.prototype:RegisterBinding(key, ID)
	if not key or not ID then return end
	if not AceLibrary("AceConsole-2.0").keybindingValidateFunc(key) then
		self:Print(string.format(L["%s is not a valid keybinding."], "|cffd9d919"..key.."|r"))
		return
	end
	for k, v in pairs(self.db.profile.Keybindings) do
		if v == key and k ~= ID then
			self.db.profile.Keybindings[k] = nil;
		elseif k == ID and v ~= key then
			self.db.profile.Keybindings[k] = nil;
			SetBinding(v) -- remove old binding
		end
	end
	self.db.profile.Keybindings[ID] = key;
	local name = self.Buttons[ID].Frame:GetName();
	SetBindingClick(key, name);
	local hotkey = _G[name.."HotKey"];
	hotkey:SetText( ShortenKeyBinding(GetBindingText(key, "KEY_")));
	-- save our new bindings
	SaveBindings(GetCurrentBindingSet());
end
-- basically from Bartender3
function Yata.Class.TotemBar.prototype:CreateTotemKeybindingOption(ID)
	local options = Yata.options.args.keybindings.args;
	local text = ""; 
	local shorttext = "";
	if(ID < 5) then
		text = L[self.Buttons[ID].Totem.Element].." "..L["Main Button"];
		shorttext = self.Buttons[ID].Totem.Element.."MainButton";
	else
		text = L[self.Buttons[ID].Totem.Element].." "..L["Menu Button"]..math.fmod(ID,10);
		shorttext = self.Buttons[ID].Totem.Element.."MenuButton"..math.fmod(ID,10);
	end
	-- Keybindings
	if(not self.db.profile.Keybindings) then
		self.db.profile.Keybindings = {};
	end
	options[shorttext] = {
		type = "text",
		name = text,
		desc = L["Assign a Keybinding to"],
		validate = "keybinding",
		order = ID,
		get = function()
			return self.db.profile.Keybindings[ID];
		end,
		set = function(k)
			if k == nil then
				self:ClearBinding(ID);
			else
				self:RegisterBinding(k,ID);
			end
		end,
	}
end


----------------
-- Totem Sets --
----------------

function Yata.Class.TotemBar.prototype:AddTotemSet(name)
	if(name == "") then return end;
		local temp = {};
		local oldone = false;
		Yata:Print(name);
		if(self.db.profile.TotemSets[name]) then 
			oldone = true;
		end
		-- clean up code incoming --
		temp = self:CreateSetFromButtons();
		self.db.profile.TotemSets[name] = temp;
		self.db.profile.ActiveSet = name;
		Yata.options.args.totemsets.args.header.name = L["Active Set:"].." "..name;
		if(not oldone) then
			self:CreateTotemSetOption(name);
		end
		Yata:UpdateText();
end
-- We basically reduce the permutations to the minimum necessary
-- if this works we can remove all that other TempTotemSet stuff
-- since this function will create the proper permutations
-- max allowed permutations is #elecount -1;
-- Start: 1 2 3 4 5
-- (1,5): 5 2 3 4 1
-- (2,3): 5 3 2 4 1
-- (2,4): 5 3 4 2 1
-- (2,1): 5 3 4 1 2
-- End  : 5 3 4 1 2
function Yata.Class.TotemBar.prototype:CreateSetFromButtons()
	local permutations = {};
	for i=1,4 do
		local currentelement = self.db.profile.TotemsOrder[i];
		if (Yata.ElementsCount[currentelement] > 0) then
			local origlayout = {};
			local endlayout = {};
			for k,v in ipairs(self.db.profile.TotemsOrder[currentelement]) do
				table.insert(origlayout,v);
			end
			local start = Yata:ReturnOrderByElement(currentelement)
			table.insert(endlayout,self.Buttons[start].Totem.Name);
			for j=1,Yata.ElementsCount[currentelement]-1 do
				table.insert(endlayout,self.Buttons[start*10+j].Totem.Name);
			end
			-- now we have a fully populated layout
			for k,v in ipairs(origlayout) do
				local s1 = v;
				local s2 = endlayout[k];
				-- interesting case if there is a difference at that position
				if(s1 ~= s2) then
					local s1pos = k; -- take position in origlayout
					local s2pos = 0;
					-- find position of the other entry which is to be swapped
					for l,w in ipairs(origlayout) do
						if(w == s2) then
							s2pos = l;
							break;
						end
					end
					-- swapping both entries
					origlayout[k] = s2;
					origlayout[s2pos] = s1;
					-- saving that permutation
					table.insert(permutations,{s1,s2});
				end
			end
		end
	end
	hidden = {};
	for k,v in self:TotemButtons() do
		if(not v.IsShown) then
			table.insert(hidden, v.Totem.Name);
		end
	end
	if(#hidden > 0) then
		permutations["hidden"] = hidden;
	end
	return permutations;
end

function Yata.Class.TotemBar.prototype:DeleteTotemSetWrapper(name)
	self.ToDelete = name;
	StaticPopup_Show("YataDeleteSet",name);
end

function Yata.Class.TotemBar.prototype:DeleteTotemSet()
	local name = self.ToDelete;
	if(name == self.db.profile.ActiveSet) then
		Yata:Print(L["Please reset first, before you delete an active set"]);
	else
		self.db.profile.TotemSets[name] =  nil;
		Yata:Print(L["Deleted"].." "..name);
		-- update options now --
		Yata.options.args.totemsets.args.loadset.args[name] = nil;
		Yata.options.args.totemsets.args.deleteset.args[name] = nil;
	end
end

function Yata.Class.TotemBar.prototype:ResetSet()
	self:UnloadTotemSet();
	self.db.profile.ActiveSet = "";
	Yata.options.args.totemsets.args.header.name = L["No active Set"];
	Yata:UpdateText();
	Yata:EditMacro();
end

function Yata.Class.TotemBar.prototype:LoadTotemSet(name)
	if(name == "") then return end;
	if(name ~= self.db.profile.ActiveSet) then
		self:UnloadTotemSet();
	end
	if(not self.db.profile.TotemSets[name]) then 
		Yata:Print(string.format(L["Set: %s does not exist"], name));
		self.db.profile.ActiveSet = "";
		return 
	end;
	for k,v in ipairs(self.db.profile.TotemSets[name]) do
		if(#v ~= 2) then 
			Yata:Print(L["Problem with Set, ignoring current set, you should delete it"]);
			return
		end
		local s1totem = v[1];
		local s2totem = v[2];
		self:Permutate(s1totem,s2totem);
	end
	local hidden = (self.db.profile.TotemSets[name])["hidden"];
	if(hidden) then
		for k,v in self:TotemButtons() do
			for l,w in ipairs(hidden) do
				if(v.Totem.Name == w) then
					self:SetButtonVisibility(v.ButtonID, false, true);
				end
			end
		end
	end
	self.db.profile.TotemSets[name] = self:CreateSetFromButtons();
	self.db.profile.ActiveSet = name;
	Yata.options.args.totemsets.args.header.name = L["Active Set:"].." "..name;
	Yata:UpdateText();
	Yata:EditMacro();
end

function Yata.Class.TotemBar.prototype:Permutate(s1totem,s2totem)
	local start = 0;
	local stop = 0;
	for l,w in self:TotemButtons() do
		if(w.Totem.Name == s1totem) then
			start = l;
		elseif(w.Totem.Name == s2totem) then
			stop = l;
		end
		if(start > 0 and stop > 0) then break; end
	end
	if(start == 0 or stop == 0) then
		return
	end
	local s1 = self.Buttons[start].Totem;
	local s2 = self.Buttons[stop].Totem;
	self.Buttons[start]:Assign(s2);
	self.Buttons[stop]:Assign(s1);
end

function Yata.Class.TotemBar.prototype:UnloadTotemSet()
	if(self.db.profile.ActiveSet == "") then return end;
	local buttonid = 0;
	for k,b in self:TotemButtons() do
		buttonid = b.ButtonID;
		if(buttonid > 10) then
			self:SetButtonVisibility(buttonid, true, true);
		end
	end
	-- unloading code here --
	-- basically permutating the whole thing backwards --
	local set = self.db.profile.TotemSets[self.db.profile.ActiveSet];
	for i=#set, 1, -1 do
			local s1totem = (set[i])[1];
			local s2totem = (set[i])[2];
			self:Permutate(s2totem,s1totem);
	end
	self.db.profile.ActiveSet = "";
end

function Yata.Class.TotemBar.prototype:SetupTotemSets()
	for k,v in pairs(self.db.profile.TotemSets) do
		self:CreateTotemSetOption(k);
	end
end

function Yata.Class.TotemBar.prototype:CreateTotemSetOption(name)
	local options = Yata.options.args.totemsets.args.loadset.args;
	options[name] = {
		name = name,
		desc = L["Load"].." "..name,
		type = "execute",
		func = function() 
			self:LoadTotemSet(name)
		end,
	}
	options = Yata.options.args.totemsets.args.deleteset.args;
	options[name] = {
		name = name,
		desc = L["Delete"].." "..name,
		type = "execute",
		func = function() 
			self:DeleteTotemSetWrapper(name);
		end,
	}
end
-----------------
-- Swap Button --
-----------------

function Yata.Class.TotemBar.prototype:ButtonDrag(start, ID)
	if(self.db.profile.ButtonLocked) then return end;
	if(start) then
		self.StartSwapButton = ID;
		PickupSpell( self.Buttons[ID].Totem.SpellID, BOOKTYPE_SPELL );
	else 
		self.StopSwapButton = ID;
		ClearCursor();
		if(self.StartSwapButton) then
			if(self.StopSwapButton == 99 and self.StartSwapButton > 10 and self.EditSet) then
				self:SetButtonVisibility(self.StartSwapButton, true, false);
			elseif(self.StopSwapButton == 100 and self.StartSwapButton > 10 and self.EditSet) then
				self:SetButtonVisibility(self.StartSwapButton, false, false);
			elseif(self.StopSwapButton < 99) then
				self:SwapButton(self.StartSwapButton, self.StopSwapButton,false);
			end
		end
		self.StartSwapButton = nil;
		self.StopSwapButton = nil;
	end
end
function Yata.Class.TotemBar.prototype:SwapButton(start, stop)
	-- Swapping buttons with the same element is easy
	local s1 = self.Buttons[start].Totem;
	local s2 = self.Buttons[stop].Totem;
	local s1ele = s1.Element;
	local s2ele = s2.Element;
	if(s1ele == s2ele) then
		if(not self.EditSet) then
			local s1pos = Yata:GetPosByTotem(s1);
			local s2pos = Yata:GetPosByTotem(s2);
			(self.db.profile.TotemsOrder[s1ele])[s2pos] = s1.Name;
			(self.db.profile.TotemsOrder[s1ele])[s1pos] = s2.Name;
		end
		-- Same Element
			self.Buttons[start]:Assign(s2);
			self.Buttons[stop]:Assign(s1);
	-- The more complicated part aka swapping whole elements is not yet implemented 
	elseif(s1ele ~= s2ele and start < 5 and stop < 5) then
		local s1pos = Yata:ReturnOrderByElement(s1ele);
		local s2pos = Yata:ReturnOrderByElement(s2ele);
		self.db.profile.TotemsOrder[s1pos] = s2ele;
		self.db.profile.TotemsOrder[s2pos] = s1ele;
		self.Buttons[start]:Assign(s2);
		self.Buttons[stop]:Assign(s1);
		Yata:Print(L["Please relock the Buttons and reload ui now"]);
	end
end

---------------------
-- Header Movement --
---------------------

function Yata.Class.TotemBar.prototype:HeaderMovement()
	local b = self.Header;
	b.Frame:EnableMouse(true);
	b.Frame:SetMovable(true);
	b.Frame:SetScript("OnDragStart", function()
		if(not self.db.profile.Locked) then
			this:StartMoving();
		end
	end)
	b.Frame:SetScript("OnDragStop", function()
		this:StopMovingOrSizing();
		self:SaveConfig();
	end);
end

-----------------------
-- Hide/Show Buttons --
-----------------------


function Yata.Class.TotemBar.prototype:CreateHideShowButtons()
	self.ShowButton = {};
	self.ShowButton.Frame = _G["YATASHOWBUTTON"];
	if(not self.ShowButton.Frame) then
		self.ShowButton.Frame = CreateFrame("Button", "YATASHOWBUTTON", UIParent, "ActionButtonTemplate");
	end
	self.ShowButton.ButtonID = 99;
	self.ShowButton.Frame:RegisterForDrag( "LeftButton" );
	self.ShowButton.Frame:SetScript("OnReceiveDrag", function() Yata.TotemBar:ButtonDrag(nil, self.ShowButton.ButtonID); end);
	self.ShowButton.Texture = self.ShowButton.Frame:CreateTexture();
	self.ShowButton.Texture:SetTexture(0, 1.0, 0, 0.75);
	self.ShowButton.Texture:SetAllPoints(self.ShowButton.Frame);
	_G["YATASHOWBUTTONName"]:SetText("Show");
	self.ShowButton.Frame:Hide();
	
	self.HideButton = {};
	self.HideButton.Frame = _G["YATAHIDEBUTTON"];
	if(not self.HideButton.Frame) then
		self.HideButton.Frame = CreateFrame("Button", "YATAHIDEBUTTON", UIParent, "ActionButtonTemplate");
	end
	self.HideButton.ButtonID = 100;
	self.HideButton.Frame:RegisterForDrag( "LeftButton" );
	self.HideButton.Frame:SetScript("OnReceiveDrag", function() Yata.TotemBar:ButtonDrag(nil, self.HideButton.ButtonID); end);
	self.HideButton.Texture = self.HideButton.Frame:CreateTexture();
	self.HideButton.Texture:SetTexture(1.0, 0, 0, 0.75);
	self.HideButton.Texture:SetAllPoints(self.HideButton.Frame);
	_G["YATAHIDEBUTTONName"]:SetText("Hide");
	self.HideButton.Frame:Hide();
end

function Yata.Class.TotemBar.prototype:ShowHideShowButtons()
	local button = 0;
	local buttonid = 0;
	for k,b in self:TotemButtons() do
		buttonid = b.ButtonID;
		if(buttonid < 10 and buttonid > button) then
			button = buttonid;
		end
	end
	local anchorTo = self.Buttons[button].Frame;
	self.HideButton.Frame:ClearAllPoints();
	self.HideButton.Frame:SetPoint("BOTTOMLEFT", anchorTo,"BOTTOMRIGHT", 20, 20);
	self.HideButton.Frame:Show();
	anchorTo = self.HideButton.Frame;
	self.ShowButton.Frame:ClearAllPoints();
	self.ShowButton.Frame:SetPoint("BOTTOMLEFT", anchorTo,"TOPLEFT", 0, 20);
	self.ShowButton.Frame:Show();
end

function Yata.Class.TotemBar.prototype:HideHideShowButtons()
	self.ShowButton.Frame:Hide();
	self.HideButton.Frame:Hide();
end

function Yata.Class.TotemBar.prototype:SetButtonVisibility(id,type,force)
	local b = self.Buttons[id];
	local buttonid = b.ButtonID;
	local max = Yata.ElementsCount[b.Totem.Element]-1 + Yata:ReturnOrderByElement(b.Totem.Element)*10;
	if(not force) then
		if(buttonid < max) then
			for i = buttonid+1,max do
				if(self.Buttons[i].IsShown ~= type) then
					return;
				end
			end
		end
	end
	b:SetVisibility(type);
end

-------------------
-- Flex Totembar --
-------------------

function Yata.Class.FlexTotemBar.prototype:init(db)
	Yata.Class.FlexTotemBar.super.prototype.init(self,db);
	-- flexbar specific below --
	if(not self.db.profile.ButtonLocked) then self.db.profile.ButtonLocked = true; end
end

-- Buttons: 1-4 are the Control Buttons, 11-1X are the MouseOver Buttons for Element 1, 21-2X for Element 2 etc.
function Yata.Class.FlexTotemBar.prototype:CreateBar()
	self.Buttons = {};			
	-- First we create the Header
	self.Header = Yata.Class.Header:new();
	for k,v in ipairs(Yata.TotemData) do
		local totem = Yata.TotemData[v];
		totem = totem[#totem];
		local number = Yata:ReturnOrderByElement(totem.Element)
		if(not self.Buttons[number]) then
			self.Buttons[number] = Yata.Class.ControlButton:new(number,self.Header);
		else
			number = number * 10 +1;
			while(self.Buttons[number]) do
				number = number + 1;
			end
			self.Buttons[number] = Yata.Class.PopupButton:new(number,self.Header);
		end
		self.Buttons[number]:Assign(totem);
	end
	-- now permutate the buttons properly
	for i=1,4 do
		local elements = self.db.profile.TotemsOrder[self.db.profile.TotemsOrder[i]];
		if(#elements) then
			for k,v in ipairs(elements) do 
				local number = k;
				if(number > 1) then
					number = number -1 + 10*i;
				else
					number = number *i;
				end
				local s1totem = v;
				local s2totem = self.Buttons[number].Totem.Name;
				self:Permutate(s1totem,s2totem);
			end
		end
	end
	-- save code --
	local count = 0;
	for i=1,4 do
		self.db.profile.TotemsOrder[self.db.profile.TotemsOrder[i]] = {};
	end
	for k,v in self:TotemButtons() do
		local totem = v.Totem;
		if(v.ButtonID < 5) then
			(self.db.profile.TotemsOrder[v.Totem.Element])[1] = v.Totem.Name;
			count = count + 1;
		else 
			(self.db.profile.TotemsOrder[v.Totem.Element])[math.fmod(v.ButtonID,10)+1] = v.Totem.Name;
			count = count + 1;
		end	
	end
	self.db.profile.TotemsCount = count;
	-- load set here --
	self:LoadTotemSet(self.db.profile.ActiveSet);
	self:SetupTotemSets();
	self:SetupKeybindings();
end

function Yata.Class.FlexTotemBar.prototype:BarUpdateHandler()
	self:UpdateCooldown();
end

function Yata.Class.FlexTotemBar.prototype:UpdateCooldown()
	-- fugly hack here but does the trick, we simply always use the SpellID of "StoneSkin Totem"
	-- to get around cooldown
	local start, duration, enable = GetSpellCooldown(self.CooldownID, BOOKTYPE_SPELL );
	for i=1,4 do
		local button = self.Buttons[i];
		if(button) then
			local cooldown = _G[button.Frame:GetName() .. "Cooldown"];
			CooldownFrame_SetTimer( cooldown, start, duration, enable );
		end
	end
end


-----------------
-- Button Swap --
-----------------

function Yata.Class.FlexTotemBar.prototype:SetupSwap(locked)
	local buttonid = 0;
	if(not locked) then
		if(self.EditSet) then
			self:ShowHideShowButtons();
		end
		for k,b in self:TotemButtons() do
			b.Frame:SetAttribute("showstates", "*");
			buttonid = b.ButtonID;
			if(buttonid > 10) then
				b.Frame.VTexture:Show();
			end
			b.Frame:Show();
		end
	else 
		if(self.EditSet) then
			self:HideHideShowButtons();
		end
		for k,b in self:TotemButtons() do
			buttonid = b.ButtonID;
			if(buttonid > 10) then
				if(b.IsShown) then
					b.Frame:SetAttribute("showstates", math.floor(buttonid/10));
				else
					b.Frame:SetAttribute("showstates", 100);
				end
				b.Frame:Hide();
				b.Frame.VTexture:Hide();
			end
		end
	end
end